﻿

namespace LS.Nc6.Web.Entry.Helper
{
    public class CommonMethodHelper
    {
        /// <summary>
        /// 对象之间相同属性的值的复制
        /// </summary>
        /// <typeparam name="D">返回的实体</typeparam>
        /// <typeparam name="S">数据源实体</typeparam>
        /// <param name="d"></param>
        /// <param name="s"></param>
        /// <returns></returns>
        public static D MapperToModel<D, S>(D d, S s)
        {
            try
            {
                var Types = s.GetType();//获得类型  
                var Typed = typeof(D);
                foreach (PropertyInfo sp in Types.GetProperties())//获得类型的属性字段  
                {
                    foreach (PropertyInfo dp in Typed.GetProperties())
                    {
                        if (dp.Name.ToLower() == sp.Name.ToLower() && dp.PropertyType == sp.PropertyType)//判断属性名是否相同  
                        {
                            dp.SetValue(d, sp.GetValue(s, null), null);//获得s对象属性的值复制给d对象的属性  
                        }
                    }
                }
            }
            catch 
            {
                throw ;
            }
            return d;
        }

        public static string GetModelProperty<D>(D d, string propertyName )
        {
            string propertyValue = string.Empty;
            try
            {
                
                var Types = d.GetType();//获得类型  
               
                foreach (PropertyInfo sp in Types.GetProperties())//获得类型的属性字段  
                {
                    if (propertyName.ToLower() == sp.Name.ToLower() )
                    {
                        propertyValue = sp.GetValue(d, null)==null?string.Empty : sp.GetValue(d, null).ToString();
                    }
                }
            }
            catch
            {
                throw;
            }
            return propertyValue;
        }

        public static D MapperToModel<D, S>(D d, S s, string[] conditioinparms)
        {
            string[] condition = { "isdeleted", "createby", "createdate" };
            IEnumerable<string> conditionwhere = null;
            if (conditioinparms != null && conditioinparms.Length > 0)
            {
                conditionwhere = condition.Concat(conditioinparms);
            }
            else
            {
                conditionwhere = condition;
            }

            try
            {
                var Types = s.GetType();//获得类型  
                var Typed = typeof(D);
                foreach (PropertyInfo sp in Types.GetProperties())//获得类型的属性字段  
                {
                    foreach (PropertyInfo dp in Typed.GetProperties())
                    {

                        if (!conditionwhere.Contains(dp.Name.ToLower()) && dp.Name.ToLower() == sp.Name.ToLower() && dp.PropertyType == sp.PropertyType && dp.CanWrite)//判断属性名是否相同  
                        {
                            //if (sp.GetValue(s, null) != null)
                            //{
                            dp.SetValue(d, sp.GetValue(s, null), null);//获得s对象属性的值复制给d对象的属性  
                            //}
                        }
                    }
                }
            }
            catch 
            {
                throw ;
            }
            return d;
        }

        /// <summary>
        ///  对象之间相同属性的值的复制
        /// </summary>
        /// <typeparam name="D">返回的实体</typeparam>
        /// <typeparam name="S">数据源实体</typeparam>
        /// <param name="s"></param>
        /// <returns></returns>
        public static D Mapper<D, S>(S s)
        {
            D d = Activator.CreateInstance<D>(); //构造新实例
            try
            {
                var Types = s.GetType();//获得类型  
                var Typed = typeof(D);
                foreach (PropertyInfo sp in Types.GetProperties())//获得类型的属性字段  
                {
                    foreach (PropertyInfo dp in Typed.GetProperties())
                    {
                        if (dp.Name.ToLower() == sp.Name.ToLower() && dp.PropertyType == sp.PropertyType)//判断属性名是否相同  
                        {
                            //if (dp.Name.ToLower()== "alarmItem" && sp.GetValue(s, null)==null)
                            //{
                            //    dp.SetValue(d, "", null);
                            //}
                            //else
                            //{
                            //    dp.SetValue(d, sp.GetValue(s, null), null);//获得s对象属性的值复制给d对象的属性  
                            //}

                            dp.SetValue(d, sp.GetValue(s, null), null);//获得s对象属性的值复制给d对象的属性 
                        }
                    }
                }
            }
            catch 
            {
                throw ;
            }
            return d;
        }


        /// <summary>
        /// 对象之间相同属性的值改变是复制
        /// </summary>
        /// <typeparam name="D">返回的实体</typeparam>
        /// <typeparam name="S">数据源实体</typeparam>
        /// <param name="d"></param>
        /// <param name="s"></param>
        /// <returns></returns>
        public static Hashtable MapperDifferentToModel<D, S>(D d, S s)
        {
            Hashtable hs = new Hashtable();
            try
            {
                var Types = s.GetType();//获得类型  
                var Typed = typeof(D);
                foreach (PropertyInfo sp in Types.GetProperties())//获得类型的属性字段  
                {
                    foreach (PropertyInfo dp in Typed.GetProperties())
                    {
                        if (dp.Name.ToLower() == sp.Name.ToLower() && dp.PropertyType == sp.PropertyType && sp.GetValue(s, null) != dp.GetValue(d, null))//判断属性名是否相同  
                        {
                            hs.Add(dp.Name.ToLower(), sp.GetValue(s, null));
                        }
                    }
                }
            }
            catch
            {
                throw ;
            }
            return hs;
        }

        /// <summary>
        /// 获取当前月天数
        /// </summary>
        /// <returns></returns>

        public static int GetMonthDays()
        {
            DateTime dt = DateTime.Today;
            int day = dt.AddDays(1 - dt.Day).AddMonths(1).AddDays(-1).Day;
            return day;
        }

        /// <summary>
        /// 获得base64图片头部分
        /// </summary>
        /// <param name="sufix"></param>
        /// <returns></returns>
        public static string GetBase64Prefix(string sufix)
        {
            return $"data:image/{sufix};base64,";
        }

        #region 同步对象属性
      public   static JsonSerializerOptions MyJsonOptions = new JsonSerializerOptions()
        {
            Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)
        };
        public static JsonSerializerOptions MyHtmlJsonOptions = new JsonSerializerOptions()
        {
            Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
        };
        /// <summary>
        /// 同步对象属性
        /// </summary>
        /// <typeparam name="T">输入对象</typeparam>
        /// <typeparam name="T2">输出对象</typeparam>
        /// <param name="t">输入对象实例</param>
        /// <param name="t2">输出对象实例</param>
        /// <param name="stream">数据流</param>
        /// <param name="extendList">扩展属实</param>
        /// <returns></returns>
        public static void GetContenxt<T, T2>(T t, T2 t2, Stream stream, List<string> extendList)
        {
            var jsonNode = GetInputStream(stream);
            var _propertyNames = ReflectionUtils.GetPropertyNames(t.GetType());
            foreach (var name in _propertyNames)
            {
                if (ContainsIgnoreCase(_propertyNames, name, out var realName))
                {
                    //处理类型
                    var propertyInfo = ReflectionUtils.GetTypeProperty(t2.GetType(), realName);

                    var propertyData = ReflectionUtils.GetTypeProperty(t.GetType(), realName);
                    if (propertyInfo != null && propertyInfo.CanWrite)
                    {
                        var propertyType = Nullable.GetUnderlyingType(propertyData.PropertyType) ?? propertyData.PropertyType;

                        if (propertyType.IsEnum)
                        {

                        }
                        else if (typeof(List<string>).IsAssignableFrom(propertyType))
                        {
                            propertyInfo.SetValue(t2, ListToString(jsonNode[realName].Deserialize<List<string>>()), null);
                        }
                        else if (typeof(string[]).IsAssignableFrom(propertyType))
                        {
                            propertyInfo.SetValue(t2, StringArryToString(jsonNode[realName].Deserialize<string[]>()), null);
                        }
                        //else if (typeof(List<MyTest>).IsAssignableFrom(propertyType))
                        //{
                        //    propertyInfo.SetValue(t2, jsonNode[realName].Deserialize<List<MyTest>>(), null);
                        //}
                        else
                        {
                           
                            if (typeof(Int32) == propertyInfo.PropertyType && jsonNode[realName] != null)
                            {
                                propertyInfo.SetValue(t2, jsonNode[realName].GetValue<string>().ParseToInt(), null);
                            }
                            else if (typeof(Int64) == propertyInfo.PropertyType && jsonNode[realName] != null)
                            {
                                
                                propertyInfo.SetValue(t2, jsonNode[realName].GetValue<string>().ParseToLong(), null);
                            }
                            else if (typeof(DateTime) == propertyInfo.PropertyType && jsonNode[realName] != null)
                            {
                                propertyInfo.SetValue(t2, jsonNode[realName].GetValue<string>().ParseToDateTime(), null);
                            }
                            else if (typeof(Boolean) == propertyInfo.PropertyType && jsonNode[realName] != null)
                            {
                                propertyInfo.SetValue(t2, jsonNode[realName].GetValue<string>().ParseToBool(), null);
                            }
                            else if (typeof(Decimal) == propertyInfo.PropertyType && jsonNode[realName] != null)
                            {
                                propertyInfo.SetValue(t2, jsonNode[realName].GetValue<string>().ParseToDecimal(), null);
                            }
                            else
                            {
                                if (jsonNode[realName] != null)
                                {
                                    propertyInfo.SetValue(t2, jsonNode[realName].ToString(), null);
                                }
                            }
                        }
                    }
                }
            }

            var propertyExtendData = ReflectionUtils.GetTypeProperty(t2.GetType(), "ExtendValues");
            if (propertyExtendData != null)
            {
                Dictionary<string, object> dictioanry = new Dictionary<string, object>();
                foreach (var item in extendList)
                {
                    if (jsonNode[item] != null)
                    {
                        dictioanry.Add(item, jsonNode[item]);
                    }
                    else
                    {
                        dictioanry.Add(item, "");
                    }
                }
               
                propertyExtendData.SetValue(t2, JsonSerializer.Serialize(dictioanry, MyHtmlJsonOptions), null);
            }
            //return t2;
        }
        public static void GetContenxt<T, T2>(T t, T2 t2, JsonNode jsonNode, List<string> extendList)
        {
            var _propertyNames = ReflectionUtils.GetPropertyNames(t.GetType());
            foreach (var name in _propertyNames)
            {
                if (ContainsIgnoreCase(_propertyNames, name, out var realName))
                {
                    //处理类型
                    var propertyInfo = ReflectionUtils.GetTypeProperty(t2.GetType(), realName);

                    var propertyData = ReflectionUtils.GetTypeProperty(t.GetType(), realName);
                    if (propertyInfo != null && propertyInfo.CanWrite)
                    {
                        var propertyType = Nullable.GetUnderlyingType(propertyData.PropertyType) ?? propertyData.PropertyType;

                        if (propertyType.IsEnum)
                        {

                        }
                        else if (typeof(List<string>).IsAssignableFrom(propertyType))
                        {
                            propertyInfo.SetValue(t2, ListToString(jsonNode[realName].Deserialize<List<string>>()), null);
                        }
                        else if (typeof(string[]).IsAssignableFrom(propertyType))
                        {
                            propertyInfo.SetValue(t2, StringArryToString(jsonNode[realName].Deserialize<string[]>()), null);
                        }
                        //else if (typeof(List<MyTest>).IsAssignableFrom(propertyType))
                        //{
                        //    propertyInfo.SetValue(t2, jsonNode[realName].Deserialize<List<MyTest>>(), null);
                        //}
                        else
                        {

                            if (typeof(Int32) == propertyInfo.PropertyType && jsonNode[realName] != null)
                            {
                                propertyInfo.SetValue(t2, jsonNode[realName].GetValue<string>().ParseToInt(), null);
                            }
                            else if (typeof(Int64) == propertyInfo.PropertyType && jsonNode[realName] != null)
                            {

                                propertyInfo.SetValue(t2, jsonNode[realName].GetValue<string>().ParseToLong(), null);
                            }
                            else if (typeof(DateTime) == propertyInfo.PropertyType && jsonNode[realName] != null)
                            {
                                propertyInfo.SetValue(t2, jsonNode[realName].GetValue<string>().ParseToDateTime(), null);
                            }
                            else if (typeof(Boolean) == propertyInfo.PropertyType && jsonNode[realName] != null)
                            {
                                propertyInfo.SetValue(t2, jsonNode[realName].GetValue<string>().ParseToBool(), null);
                            }
                            else if (typeof(Decimal) == propertyInfo.PropertyType && jsonNode[realName] != null)
                            {
                                propertyInfo.SetValue(t2, jsonNode[realName].GetValue<string>().ParseToDecimal(), null);
                            }
                            else
                            {
                                if (jsonNode[realName] != null)
                                {
                                    propertyInfo.SetValue(t2, jsonNode[realName].ToString(), null);
                                }
                            }
                        }
                    }
                }
            }

            var propertyExtendData = ReflectionUtils.GetTypeProperty(t2.GetType(), "ExtendValues");
            if (propertyExtendData != null)
            {
                Dictionary<string, object> dictioanry = new Dictionary<string, object>();
                foreach (var item in extendList)
                {
                    if (jsonNode[item] != null)
                    {
                        dictioanry.Add(item, jsonNode[item]);
                    }
                    else
                    {
                        dictioanry.Add(item, "");
                    }
                }

                propertyExtendData.SetValue(t2, JsonSerializer.Serialize(dictioanry, MyHtmlJsonOptions), null);
            }
            //return t2;
        }
        public static JsonNode GetInputStream(Stream stream)
        {
            string json = string.Empty;
            using (StreamReader sr = new StreamReader(stream, Encoding.UTF8))
            {
                json = sr.ReadToEndAsync().GetAwaiter().GetResult();
            }

            return string.IsNullOrEmpty(json) ? null : JsonNode.Parse(json);
        }
       
       
        private static bool ContainsIgnoreCase(IEnumerable<string> list, string name, out string realName)
        {
            realName = null;
            foreach (var x in list)
            {
                if (!StringComparer.OrdinalIgnoreCase.Equals(x, name)) continue;

                realName = x;
                return true;
            }

            return false;
        }

        public static string ListToString(List<string> objects, string separator = ",")
        {
            return objects != null && objects.Count > 0 ? string.Join(separator, objects) : string.Empty;
        }
        public static string StringArryToString(string[] objects, string separator = ",")
        {
            return objects != null && objects.Length > 0 ? string.Join(separator, objects) : string.Empty;
        }
        #endregion


    }
}
